home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / asmutil / afloat.zip / F_SUB.ASM < prev    next >
Assembly Source File  |  1988-03-15  |  4KB  |  183 lines

  1.         PAGE ,132
  2. ;----------------------------------------------------------
  3. ; F_SUB -- version for use with assembly-language programs
  4. ;
  5. ; Copyright Bob Kline 1988
  6. ;
  7. ; Purpose:
  8. ;       Subtract one single-precision floating-point number
  9. ;       from another.
  10. ;
  11. ; Input:
  12. ;       Minuend in DX:AX and subtrahend in CX:BX as 4-byte reals
  13. ;       to be subtracted in IEEE format.
  14. ;
  15. ; Output:
  16. ;       Result (IEEE) is single-precision real in DX:AX.
  17. ;
  18. ; Other registers affected:
  19. ;       BX, CX, DI, SI, BP
  20. ;
  21. ; Procedures:
  22. ;       F_ADD
  23. ;
  24. ; Comments:
  25. ;       Sets external variable _errno to ERANGE if over-
  26. ;       flow occurs.  If a calling routine will be testing
  27. ;       _errno, it must first reset the variable to zero
  28. ;       to be sure that an error code is not left over
  29. ;       from some previous call.  If the signs of the two
  30. ;       operands differ the sign of the subtrahend is
  31. ;       flipped and F_ADD is called.
  32. ;----------------------------------------------------------
  33.  
  34.         .MODEL  SMALL
  35.  
  36.     PUBLIC    F_SUB
  37.     EXTRN    _errno:WORD,F_ADD:PROC
  38.  
  39. ERANGE    EQU    34
  40.  
  41.     .CODE
  42.  
  43. F_SUB    PROC
  44.  
  45. ; check the sign
  46.     MOV    SI,DX
  47.     XOR    SI,CX
  48.     JNS    SAME_SIGNS
  49.  
  50. ; signs are different -- change sign of subtrahend
  51. ;   and use F_ADD
  52.     XOR    CX,8000h
  53.     CALL    F_ADD
  54.     RET
  55.  
  56. ; sign same for both -- save it
  57. SAME_SIGNS:
  58.     MOV    SI,DX
  59.     AND    SI,8000h
  60.     PUSH    SI
  61.  
  62. ; unpack exponent and remove bias
  63.     MOV    DI,DX
  64.     MOV    SI,CX
  65.     SHL    DX,1
  66.     SHL    CX,1
  67.     XCHG    DH,DL
  68.     XCHG    CH,CL
  69.     XOR    DH,DH
  70.     XOR    CH,CH
  71.     SUB    DX,127
  72.     SUB    CX,127
  73.     XCHG    DI,DX
  74.     XCHG    SI,CX
  75.  
  76. ; unpack the mantissas & slide over to the left
  77. ;   one position so we'll have elbowroom to catch
  78. ;   any lost low bit for rounding
  79.     AND    DX,7Fh
  80.     AND    CX,7Fh
  81.     OR    DX,80h
  82.     OR    CX,80h
  83.     SHL    AX,1
  84.     RCL    DX,1
  85.     SHL    BX,1
  86.     RCL    CX,1
  87.  
  88. ; use BP instead of CX for high word of subtrahend so
  89. ;   we can use CX for shift counting
  90.     MOV    BP,CX
  91.  
  92. ; check to see which number is bigger
  93.     CMP    DI,SI
  94.     JG    SUBTRAHEND_LOWER
  95.     JL    MINUEND_LOWER
  96.     CMP    DX,BP
  97.     JG    SUBTRAHEND_LOWER
  98.     JL    MINUEND_LOWER
  99.     CMP    AX,BX
  100.     JG    SUBTRAHEND_LOWER
  101.     JL    MINUEND_LOWER
  102.  
  103. ; operands equal -- return 0.0
  104.     POP    SI
  105.     XOR    AX,AX
  106.     XOR    DX,DX
  107.     RET
  108.  
  109. ; the minuend is lower than the subtrahend -- swap
  110. ;   operands & flip the sign
  111. MINUEND_LOWER:
  112.     XCHG    DX,BP
  113.     XCHG    AX,BX
  114.     XCHG    DI,SI
  115.     POP    CX
  116.     XOR    CX,8000h
  117.     PUSH    CX
  118.  
  119. ; now the subtrahend is lower than the minuend --
  120. ;   if the exponents are different adjust subtrahend
  121. ;   so that they're the same
  122. SUBTRAHEND_LOWER:
  123.     MOV    CX,DI
  124.     SUB    CX,SI
  125.         JZ      DO_SUB
  126.  
  127. ; if the second number is so much smaller than than first
  128. ;   that subtracting it in will not make any difference, don't bother
  129.     CMP    CX,24
  130.     JA    SHIFTBACK
  131.  
  132. ; here's the shift-right loop for the subtrahend
  133. LOOP1:    SHR    BP,1
  134.     RCR    BX,1
  135.     LOOP    LOOP1
  136.  
  137. ; do the subtraction
  138. DO_SUB: SUB     AX,BX
  139.     SBB    DX,BP
  140.  
  141. ; see if we need to shift back to the right and round
  142. SHIFTBACK:
  143.         TEST    DX,100h
  144.     JZ    SHIFTUP
  145.     ADD    AX,1
  146.     ADC    DX,0
  147.     SHR    DX,1
  148.     RCR    AX,1
  149.     JMP    SHORT REPACK
  150.  
  151. ; normalize mantissa if necessary
  152. LOOP2:    SHL    AX,1
  153.     RCL    DX,1
  154. SHIFTUP:
  155.     DEC    DI
  156.     TEST    DX,80h
  157.     JZ    LOOP2
  158.  
  159. ; make top bit of mantissa invisible -- it's understood
  160. REPACK: AND    DX,7Fh
  161.  
  162. ; restore exponent bias
  163.     MOV    BX,DI
  164.     ADD    BX,127
  165.  
  166. ; test for valid exponent and re-pack
  167.     OR    BH,BH
  168.     JZ    EXP_OK
  169.     MOV    _errno,ERANGE
  170.     XOR    BH,BH
  171. EXP_OK: XCHG    BH,BL
  172.     SHR    BX,1
  173.     OR    DX,BX
  174.  
  175. ; get sign back and we're done
  176.     POP    CX
  177.     OR    DX,CX
  178.     RET
  179.  
  180. F_SUB   ENDP
  181.  
  182.     END
  183.